<?php


namespace App\Controller\Frontend;


use App\Entity\Page;
use App\Entity\PageComment;
use App\Entity\Setting;
use App\Message\PageCommentReply;
use App\Service\Redis;
use App\Utils\Traits\JsonTrait;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Messenger\MessageBusInterface;
use Symfony\Component\Routing\Annotation\Route;

class ArticleController extends AbstractController {
    use JsonTrait;

    private $redis;
    private $limit = 5;

    public function __construct (Redis $client) {
        $this->redis = $client->redis;
    }

    /**
     * 文章详情
     * @param Request $request
     * @param $id
     * @Route("/article/{id}", name="article_content", requirements={"id"="\d+"})
     * @Template()
     * @return array|\Symfony\Component\HttpFoundation\RedirectResponse
     */
    public function index (Request $request, $id) {
        $page = $this->getDoctrine()->getRepository(Page::class)->findOneBy(['id' => $id, 'status' => 1]);
        if (!is_object($page)) {
            return $this->redirectToRoute('not_found_page');
        }

        $page->setPageView($page->getPageView() + 1);
        $this->getDoctrine()->getManager()->flush();
        return [
            'page' => $page,
        ];
    }

    /**
     * 文章详情-其他
     * @param $id
     * @param $comment_num
     * @return array|\Symfony\Component\HttpFoundation\Response
     */
    public function other ($id, $comment_num = 0) {
        $page = $this->getDoctrine()->getRepository(Page::class)->find($id);
        $prev = $this->getDoctrine()->getRepository(Page::class)->getPrevPage($id);
        $next = $this->getDoctrine()->getRepository(Page::class)->getNextPage($id);
        $related = $this->getDoctrine()->getRepository(Page::class)->getRelatedPage($id);
        $comments = $this->getDoctrine()->getRepository(PageComment::class)->findBy(['page_id' => $id, 'status' => true], ['id' => 'DESC'], $this->limit, 0);
        return $this->render('frontend/article/other.html.twig', [
            'page'        => $page,
            'comment_num' => $comment_num,
            'prev'        => $prev,
            'next'        => $next,
            'related'     => $related,
            'comments'    => $comments,
        ]);
    }

    /**
     * 评论
     * @Route("/article/reply", name="page_reply", methods={"POST"})
     * @param Request $request
     * @param MessageBusInterface $bus
     * @return \Symfony\Component\HttpFoundation\JsonResponse
     * @throws \Exception
     */
    public function reply (Request $request, MessageBusInterface $bus) {
        if ($request->isXmlHttpRequest()) {
            $page_comment = null;
            $comment_id = $request->request->getInt('comment_id', 0);
            $page_id = $request->request->getInt('page_id', 0);
            $page = $this->getDoctrine()->getRepository(Page::class)->find($page_id);
            $setting = $this->getDoctrine()->getRepository(Setting::class)->getCurrentSetting();
            // 避免频繁发布评论，同一篇文章同一个IP，一小时只允许评论5次
            $ip = $request->getClientIp();
            $redis_key = $this->getParameter('app.name').':article:reply:'.$ip.'.'.$page_id;
            if ($this->redis->exists($redis_key)) {
                $redis_value = $this->redis->get($redis_key);
                $redis_ttl = $this->redis->ttl($redis_key);
                if ($redis_value >= 5) {
                    return $this->jsonFailure('评论过于频繁，请稍后再操作');
                }
                $this->redis->incr($redis_key);
                $this->redis->expire($redis_key, $redis_ttl);
            } else {
                $this->redis->setex($redis_key, 3600, 1);
            }
            // 数据校验
            if (!is_object($page)) {
                return $this->jsonFailure('请求的资源不存在');
            }
            if (!$page->getIsComment()) {
                return $this->jsonFailure('该文章未开启评论功能');
            }
            if (!$setting->getIsComment()) {
                return $this->jsonFailure('系统未开启评论功能');
            }
            if ($comment_id !== 0) {
                $page_comment = $this->getDoctrine()->getRepository(PageComment::class)->find($comment_id);
                if (!is_object($page_comment)) {
                    return $this->jsonFailure('请求的资源不存在');
                }
            }
            // 保存评论
            $comment = new PageComment();
            $comment->setPageId($page->getId());
            $comment->setParentId($comment_id);
            $comment->setNickname($request->request->get('author', '-'));
            $comment->setComment($request->request->get('comment', ''));
            $comment->setEmail($request->request->get('email', null));
            $comment->setStatus($setting->getIsAutoPassComment());
            $comment->setIp($request->getClientIp());
            $comment->setCreatedAt(new \DateTime());
            $this->getDoctrine()->getManager()->persist($comment);
            $this->getDoctrine()->getManager()->flush();
            if ($setting->getIsAutoPassComment()) {
                // 如果是回复，则邮件通知被回复用户
                if ($comment_id != 0) {
                    $bus->dispatch(new PageCommentReply($comment->getId()));
                }
                return $this->jsonSuccess([
                    'message' => '发表成功',
                    'comment' => $this->getDoctrine()->getRepository(PageComment::class)->getCommentByById($comment->getId()),
                ]);
            } else {
                return $this->jsonSuccess(['message' => '发表成功，审核通过后会自动展示']);
            }
        } else {
            return $this->jsonFailure('请求错误');
        }
    }

    /**
     * 评论-分页
     * @Route("/article/reply_more", name="page_reply_more", methods={"POST"})
     * @param Request $request
     * @return \Symfony\Component\HttpFoundation\JsonResponse|\Symfony\Component\HttpFoundation\Response
     */
    public function replyMore (Request $request) {
        if ($request->isXmlHttpRequest()) {
            $page = $this->getDoctrine()->getRepository(Page::class)->find($request->request->getInt('page_id', 0));
            if (!is_object($page)) {
                return $this->jsonFailure('请求的资源不存在');
            }
            if (!$page->getIsComment()) {
                return $this->jsonFailure('该文章未开启评论功能');
            }
            $setting = $this->getDoctrine()->getRepository(Setting::class)->getCurrentSetting();
            if (!$setting->getIsComment()) {
                return $this->jsonFailure('系统未开启评论功能');
            }
            $offset = $request->request->getInt('offset', 1);
            $comments = $this->getDoctrine()->getRepository(PageComment::class)->getCommentByPaginator($page->getId(), $this->limit, $offset);
            return $this->jsonSuccess([
                'comments' => $comments,
                'offset'   => $offset + 1,
                'total'    => count($comments),
            ]);
        } else {
            return $this->jsonFailure('请求错误');
        }
    }
}